<!--
 * @Author: DESKTOP-D0D7KKT\Administrator 18368095041@163.com
 * @Date: 2024-12-30 17:43:37
 * @LastEditors: 吴世扬 18368095041@163.com
 * @LastEditTime: 2025-05-23 15:15:49
 * @FilePath: /vue3-admin/src/components/ui/GanttTable/GanttTable.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->

<script lang="ts" setup>
import { renderSlot, type VNode } from 'vue';
import dayjs from 'dayjs';
import isSameOrBeforePlugin from 'dayjs/plugin/isSameOrBefore';
import isSameOrAfterPlugin from 'dayjs/plugin/isSameOrAfter';

import {
    // ElTableColumn,
    type TableColumnCtx,
    type TableProps
} from 'element-plus/es/components/table/index';
import { ElTableColumn, ElTable } from 'element-plus';

import { treeToArray } from '@/utils';

import BarView from './components/BarView.vue';

dayjs.extend(isSameOrBeforePlugin);
dayjs.extend(isSameOrAfterPlugin);

type TableTreeData = {
    children?: TableTreeData[];
} & Record<string, unknown>;

interface CptProps extends TableProps<unknown> {
    ganttColprop?: string;
    ganttRowProps?: {
        id: string;
        name: string;
        start: string;
        end: string;
        progress?: string;
        status: string;
        // dependencies?: string;
    };
    rowKey?: string;
}

const props = withDefaults(defineProps<CptProps>(), {
    ganttColprop: 'gantt',
    ganttRowProps: () => ({
        id: 'id',
        name: 'name',
        start: 'start',
        end: 'end',
        progress: 'progress', // number 0 ~ 1
        status: 'status' // 'planned' | 'ongoing' | 'finish' | 'error'
        // dependencies: 'dependencies'
    }),
    rowKey: 'id'
});

const { ganttColprop, ganttRowProps, data, rowKey } = toRefs(props);

const list = treeToArray(rowKey.value, data.value as TableTreeData[]);

const slots = defineSlots<{
    default: any;
}>();

const slotsDefault = slots.default();

const hasGanttCol = () => {
    return slotsDefault.findIndex(
        (item: VNode) => item.props?.prop === ganttColprop.value
    );
};

const getDateRange = (dateList: (dayjs.Dayjs | undefined)[]) => {
    // 初始化最早和最晚日期为 undefined
    let earliestDate: dayjs.Dayjs | undefined;
    let latestDate: dayjs.Dayjs | undefined;

    // 遍历数组以找到最早和最晚日期
    dateList.forEach((date) => {
        if (date) {
            if (earliestDate === undefined || date.isBefore(earliestDate)) {
                earliestDate = date;
            }
            if (latestDate === undefined || date.isAfter(latestDate)) {
                latestDate = date;
            }
        }
    });

    return [earliestDate, latestDate];
};

const getDateListByRange = (start?: dayjs.Dayjs, end?: dayjs.Dayjs) => {
    if (start === undefined || end === undefined)
        return {
            date: [],
            month: [],
            year: []
        };
    // 遍历日期范围
    const dateList = [];
    const monthList = [];
    const yearList = [];
    let currentDate = start.clone();
    while (currentDate.isSameOrBefore(end)) {
        dateList.push(currentDate.format('YYYY-MM-DD')); // 将日期格式化为字符串并添加到数组中
        currentDate = currentDate.add(1, 'day'); // 日期加一天
    }
    currentDate = start.clone();
    while (currentDate.isSameOrBefore(end)) {
        monthList.push(currentDate.format('YYYY-MM'));
        currentDate = currentDate.add(1, 'month');
    }
    if (!monthList.includes(end.format('YYYY-MM'))) {
        monthList.push(end.format('YYYY-MM'));
    }
    currentDate = start.clone();
    while (currentDate.isSameOrBefore(end)) {
        yearList.push(currentDate.format('YYYY'));
        currentDate = currentDate.add(1, 'year');
    }
    if (!yearList.includes(end.format('YYYY'))) {
        yearList.push(end.format('YYYY'));
    }
    return {
        date: dateList,
        month: monthList,
        year: yearList
    };
};

const index = hasGanttCol();
const vnodeList = slots.default();
if (index !== -1) {
    const ganttColVNode: VNode = vnodeList[index];
    const dateRange = getDateRange([
        ...list.map((item) => {
            if (ganttRowProps.value.start) {
                const start = item[ganttRowProps.value.start] as string;
                return dayjs(start);
            }
        }),
        ...list.map((item) => {
            if (ganttRowProps.value.end) {
                const end = item[ganttRowProps.value.end] as string;
                return dayjs(end);
            }
        })
    ]);
    const dateObj = getDateListByRange(dateRange[0], dateRange[1]);
    console.log(dateObj);

    vnodeList.splice(
        index,
        1,
        // dateObj.year.map((y) =>
        //     h(
        //         ElTableColumn,
        //         {
        //             label: y + '年',
        //             align: 'center'
        //         },
        //         () => [
        //             dateObj.month
        //                 .filter((m) => m.indexOf(y) !== -1)
        //                 .map((m) =>
        //                     h(
        //                         ElTableColumn,
        //                         {
        //                             label: dayjs(m).format('M') + '月',
        //                             align: 'center'
        //                         },
        //                         () => [
        //                             dateObj.date
        //                                 .filter((d) => d.indexOf(m) !== -1)
        //                                 .map((d) =>
        //                                     h(ElTableColumn, {
        //                                         label: dayjs(d).format('D'),
        //                                         align: 'center'
        //                                     })
        //                                 )
        //                         ]
        //                     )
        //                 )
        //         ]
        //     )
        // ),
        h(
            ElTableColumn,
            {
                ...ganttColVNode.props,
                minWidth: dateObj.date.length * 120
            },
            {
                header: () => {
                    return h(
                        'div',
                        {
                            style: {
                                'white-space': 'nowrap'
                            }
                        },
                        dateObj.date.map((d) =>
                            h(
                                'div',
                                {
                                    style: {
                                        width: '120px',
                                        display: 'inline-block',
                                        'text-align': 'center'
                                    }
                                },
                                dayjs(d).format('YYYY-MM-DD')
                            )
                        )
                    );
                },
                default: (scoped: any) => {
                    // 进度放后端判断
                    let left = 0;
                    let width = 0;
                    let start: dayjs.Dayjs | undefined;
                    let end: dayjs.Dayjs | undefined;
                    if (
                        ganttRowProps.value.start &&
                        ganttRowProps.value.end &&
                        dateRange[0] &&
                        dateRange[1]
                    ) {
                        start = dayjs(scoped.row[ganttRowProps.value.start]);
                        end = dayjs(scoped.row[ganttRowProps.value.end]);
                        left = start.diff(dateRange[0], 'day');
                        width = end.diff(start, 'day') + 1;
                    }

                    let progress = 0;
                    let type: 'green' | 'red' | 'orange' = 'orange';
                    if (ganttRowProps.value.status) {
                        // 完成、错误、计划中
                        if (
                            scoped.row[ganttRowProps.value.status] === 'finish'
                        ) {
                            progress = 1;
                            type = 'green';
                        } else if (
                            scoped.row[ganttRowProps.value.status] === 'error'
                        ) {
                            progress = 1;
                            type = 'red';
                        } else if (
                            scoped.row[ganttRowProps.value.status] === 'planned'
                        ) {
                            progress = 0;
                        } else {
                            progress =
                                ganttRowProps.value.progress &&
                                scoped.row[ganttRowProps.value.progress]
                                    ? scoped.row[ganttRowProps.value.progress]
                                    : 0;
                            // // 进行中
                            // if (
                            //     scoped.row.children &&
                            //     scoped.row.children.length > 0
                            // ) {
                            //     // 多项任务

                            // } else {
                            //     // 单项任务
                            //     if (start === undefined || end === undefined) {
                            //         progress = 0;
                            //     } else {
                            //         if (dayjs().isBefore(start)) {
                            //             progress = 0;
                            //         } else {
                            //             const ratio =
                            //                 (dayjs().diff(start) + 1) /
                            //                 (end.diff(start) + 1);
                            //             if (ratio >= 1) {
                            //                 progress = 1;
                            //                 type = 'green';
                            //             } else {
                            //                 progress = ratio;
                            //             }
                            //         }
                            //     }
                            // }
                        }
                    }
                    return h(
                        'div',
                        {
                            position: 'relative'
                        },
                        h(BarView, {
                            type,
                            progress,
                            style: {
                                width: width * 120 + 'px',
                                left: left * 120 + 'px'
                            }
                        })
                    );
                }
            }
        )
    );
    console.log(
        ganttColVNode,
        slots.default,
        slots.default(),
        getCurrentInstance()
    );
}

const GanttTableNode = defineComponent({
    render: () => {
        return h(
            ElTable,
            {
                className: 'gantttable-container',
                data: data.value,
                rowKey: rowKey.value
            },
            () => vnodeList
        );
    }
});
</script>

<template>
    <GanttTableNode />
</template>

<style lang="scss" scoped>
.gantttable-container {
    width: 100%;
    height: 100%;
}
</style>
